package org.study.minio.boot.controller;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.*;
import com.qcloud.cos.utils.IOUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.study.minio.boot.config.CosProperties;
import org.study.minio.boot.service.CosService;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 腾讯云 COS 对象存储控制器
 * 官方文档：https://cloud.tencent.com/document/product/436/10199
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2024年05月18日
 */
@RestController
@RequestMapping("/cos")
public class CosController {
    public static final String DIR_IMAGES = "images/";
    public static final String DIR_VIDEOS = "videos/";
    @Resource
    private CosProperties cosProperties;
    @Autowired(required = false)
    private COSClient cosClient;
    @Autowired(required = false)
    private CosService cosService;

    @GetMapping(value = "/listBuckets")
    public List<String> listBuckets() {
        List<Bucket> bucketList = cosService.listBuckets();
        List<String> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(bucketList)) {
            list = bucketList.parallelStream()
                    .map(item -> item.getName())
                    .collect(Collectors.toList());
        }
        return list;
    }

    @GetMapping(value = "/listObjects")
    public List<String> listObjects() {
        ObjectListing objectListing = cosService.listObjects(cosProperties.getBucketName(), DIR_IMAGES);
        List<String> list = new ArrayList<>();
        if (objectListing != null && !CollectionUtils.isEmpty(objectListing.getObjectSummaries())) {
            list = objectListing.getObjectSummaries().parallelStream()
                    .map(item -> item.getKey())
                    .collect(Collectors.toList());
        }
        return list;
    }

    @DeleteMapping(value = "/deleteObject")
    public String deleteObject() {
        cosService.deleteObject(cosProperties.getBucketName(), "images/test.pdf");
        return "删除成功";
    }

    @DeleteMapping(value = "/deleteObjects")
    public Map<String, Object> deleteObjects() {
        List<String> deleteKeys = Arrays.asList("1.png", "10.png", "100.png");
        List<String> deleteObjects = cosService.deleteObjects(cosProperties.getBucketName(), deleteKeys);
        Map<String, Object> result = new HashMap<>(3);
        result.put("code", "0000");
        result.put("msg", "删除成功");
        result.put("data", deleteObjects);
        return result;
    }

    @GetMapping(value = "/downloadToLocal")
    public Map<String, String> downloadToLocal() {
        Map<String, String> result = cosService.downloadToLocal(cosProperties.getBucketName(), "protocol/1649834912417.pdf", cosProperties.getDownloadPath());
        return result;
    }

    @GetMapping(value = "/downloadByBytes")
    public void downloadByBytes(HttpServletResponse response) {
        byte[] cosContent = cosService.getObjectBytes(cosProperties.getBucketName(), "protocol/1649834912417.pdf");
        try (ByteArrayInputStream bais = new ByteArrayInputStream(cosContent);
             OutputStream os = response.getOutputStream()) {
            IOUtils.copy(bais, os);
            os.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @GetMapping(value = "/downloadByInputStream")
    public void downloadByInputStream(HttpServletResponse response) {
        String fileName = "1649834912417.pdf";
        // 清空 response
        response.reset();
        // 设置 response 的 Header，处理中文乱码
        response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
        response.setContentType("application/download");
        GetObjectRequest getObjectRequest = new GetObjectRequest(cosProperties.getBucketName(), "protocol/" + fileName);
        COSObject cosObject = cosClient.getObject(getObjectRequest);
        try (COSObjectInputStream cosObjectInput = cosObject.getObjectContent()) {
            byte[] buffer = new byte[cosObjectInput.available()];
            try (OutputStream os = response.getOutputStream()) {
                os.write(buffer);
                os.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @PostMapping(value = "/upload")
    public Map<String, Object> uploadFile(@RequestParam(value = "file") MultipartFile file) {
        Map<String, Object> result = new HashMap<>(2);
        result.put("code", "0000");
        result.put("msg", "上传成功");
        if (file == null) {
            result.put("code", "9999");
            result.put("msg", "文件为空");
            return result;
        }
        // 文件大小，单位是字节
        long fileSize = file.getSize();
        String fileName = file.getOriginalFilename();
        String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
        String newFileName = UUID.randomUUID() + fileSuffix;
        String bucketName = cosProperties.getBucketName();
        try {
            // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口，大文件上传请参照 API 文档高级 API 上传
            File localFile = File.createTempFile("temp", fileSuffix);
            file.transferTo(localFile);
            // 指定要上传到 COS 上的路径
            String key = DIR_IMAGES + newFileName;
            if (!cosClient.doesBucketExist(bucketName)) {
                // 仓库不存在，则创建仓库
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                // 设置为公有读私有写
                createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
                cosClient.createBucket(createBucketRequest);
            }
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
            result.put("data", cosProperties.getBasePath() + key);
            return result;
        } catch (IOException ex) {
            result.put("code", "9999");
            result.put("msg", ex.getMessage());
            return result;
        }
    }
}
